package com.gitee.wsl.unit.length

import com.gitee.wsl.unit.BaseUnit
import kotlin.Double


sealed class LengthUnit( value:Double, type: LengthUnitType): BaseUnit<Double, LengthUnitType>(value, type) {

    abstract class Fixed(value:Double, type: LengthUnitType) : LengthUnit(value,type)
    abstract class Variable(value:Double, type: LengthUnitType) : LengthUnit(value,type)

    override fun toBase(): Double {
        return value * type.baseUnit
    }

    class M(value:Double): Fixed(value, LengthUnitType.M){
        override fun format(): String ="$value M"
    }

    class KM(value: Double): Fixed(value, LengthUnitType.KM){
        override fun format(): String ="$value KM"
    }

    class DM(value: Double): Fixed(value, LengthUnitType.DM){
        override fun format(): String ="$value DM"
    }

    class CM(value: Double): Fixed(value, LengthUnitType.CM){
        override fun format(): String ="$value CM"
    }

    class MM(value: Double): Fixed(value, LengthUnitType.MM){
        override fun format(): String ="$value MM"
    }

    class UM(value: Double): Fixed(value, LengthUnitType.UM){
        override fun format(): String ="$value UM"
    }

    class NM(value: Double): Fixed(value, LengthUnitType.NM){
        override fun format(): String ="$value NM"
    }

    class PM(value: Double): Fixed(value, LengthUnitType.PM){
        override fun format(): String ="$value PM"
    }

    class FM(value: Double): Fixed(value, LengthUnitType.FM){
        override fun format(): String ="$value FM"
    }

    class IN(value: Double): Fixed(value, LengthUnitType.IN){
        override fun format(): String ="$value IN"
    }

    override fun convertTo(desType: LengthUnitType): LengthUnit{
        if(this.type == desType) return this
        return convert(toBase(),desType)
    }

    private fun convert(base:Double,desType: LengthUnitType): LengthUnit{
        val newValue = base / desType.baseUnit
        return when(desType){
            is LengthUnitType.M -> M(newValue)
            is LengthUnitType.KM -> KM(newValue)
            is LengthUnitType.DM -> DM(newValue)
            is LengthUnitType.CM -> CM(newValue)
            is LengthUnitType.FM -> FM(newValue)
            is LengthUnitType.MM -> MM(newValue)
            is LengthUnitType.UM -> UM(newValue)
            is LengthUnitType.NM -> NM(newValue)
            is LengthUnitType.PM -> PM(newValue)

            else -> throw IllegalArgumentException("不支持的转换单位")
        }
    }

    companion object{
        val ZERO = M(0.0)
    }
}


val Number.M get() = LengthUnit.M(this.toDouble())

val Number.MM get() = LengthUnit.MM(this.toDouble())

val Number.KM get() = LengthUnit.KM(this.toDouble())

val Number.INCH get() = LengthUnit.IN(this.toDouble())